{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from numba import njit\n",
    "\n",
    "# 指标函数，计算收盘价减去移动平均值（CMMA），可用于 均值回归 策略：\n",
    "# 如果CMMA值为正，那么当前价格高于其移动平均值；如果CMMA值为负，那么当前价格低于其移动平均值。\n",
    "def cmma(bar_data, lookback):\n",
    "\n",
    "    @njit  # Enable Numba JIT.\n",
    "    def vec_cmma(values):   #values 是输入的收盘价数组。\n",
    "        # Initialize the result array.\n",
    "        n = len(values)\n",
    "        out = np.array([np.nan for _ in range(n)])\n",
    "\n",
    "        # For all bars starting at lookback:\n",
    "        # 函数内部通过一个循环来遍历 values 数组，对于每个位置 i（从 lookback-1 开始），\n",
    "        # 它计算了从 i-lookback+1 到 i（包括 i）的 values 数组子集的平均值，\n",
    "        # 然后将当前价格 values[i] 减去这个平均值，得到的结果存储在输出数组 out 的相应位置\n",
    "        for i in range(lookback, n):\n",
    "            # Calculate the moving average for the lookback.\n",
    "            ma = 0\n",
    "            for j in range(i - lookback, i):\n",
    "                ma += values[j]\n",
    "            ma /= lookback\n",
    "            # Subtract the moving average from value.\n",
    "            out[i] = values[i] - ma\n",
    "        return out\n",
    "\n",
    "    # Calculate with close prices.\n",
    "    return vec_cmma(bar_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 示例使用  \n",
    "close_prices = np.array([10, 11, 12, 13, 14, 15, 16, 17, 18])  # 收盘价示例  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([nan, nan, nan,  2.,  2.,  2.,  2.,  2.,  2.])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cmma(close_prices, lookback=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "close_prices = np.array([10, 11, 12, 13, 14, 15, 16, 17, 18, 16, 15, 14, 10])  # 收盘价示例  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([        nan,         nan,         nan,  2.        ,  2.        ,\n",
       "        2.        ,  2.        ,  2.        ,  2.        , -1.        ,\n",
       "       -2.        , -2.33333333, -5.        ])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cmma(close_prices, lookback=3)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
